import ArrayMethods from "./arr";
import Dep from './dep'

export function observer(data) {
  if (typeof data !== 'object' || data === null) {
    return data
  }
  return new Observer(data)
}

class Observer {
  constructor(value) {
    // 给监听的数据顶一个属性
    Object.defineProperty(value, '__ob__', {
      enumerable: false,
      value: this
    });
    this.dep = new Dep(); // 给所有的对象类型添加一个dep
    if (Array.isArray(value)) {
      value.__proto__ = ArrayMethods;
      this.observeArray(value);
      return;
    }
    this.walk(value);
  }
  walk(data) {
    let keys = Object.keys(data);
    for (let i = 0; i < keys.length; i++) {
      let key = keys[i];
      let value = data[key];
      defineReactive(data, key, value)
    }
  }
  observeArray(value) {
    for (let i = 0; i < value.length; i++) {
      observer(value[i])
    }
  }
}

function defineReactive(data, key, value) {
  let childDep = observer(value); // 递归绑定对象值
  // 对所有属性进行劫持
  let dep = new Dep(); // 给每一个属性添加Dep
  Object.defineProperty(data, key, {
    get() {
      // 收集依赖
      if (Dep.target) {
        dep.depend();
        if (childDep.dep) {
          childDep.dep.depend(); // 数组收集
        }
      }
      return value
    },
    set(newValue) {
      if (newValue === value) {
        return;
      }
      observer(newValue); // 每次修改值动态更新
      value = newValue;
      dep.notify();
    }
  })
}